using System.Collections.Generic;
using FireStarter.Base;
using FireStarter.CodeGeneration;
using FireStarter.CodeGeneration.Generator;
using FireStarterModeller.BO;
using NUnit.Framework;

namespace FireStarter.Test.CodeGeneration.Generator
{
    [TestFixture]
    public class TestCollectionDelegatesDictionary : TestBase
    {
        [Test]
        public void TestDefaultDelegatesAvailable()
        {
            //---------------Set up test pack-------------------

            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            CollectionDelegatesDictionary collectionDelegatesDictionary = new CollectionDelegatesDictionary();
            //---------------Test Result -----------------------
            Assert.AreEqual(1, collectionDelegatesDictionary.Count);
            Assert.IsTrue(collectionDelegatesDictionary.ContainsKey("ModelClasses_OrderedForDeletion"));
        }

        [Test]
        public void Test_CaseInsensitive()
        {
            //---------------Set up test pack-------------------
            CollectionDelegatesDictionary collectionDelegatesDictionary = new CollectionDelegatesDictionary();
            const string propertyName = "Abc1";
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            collectionDelegatesDictionary.Add(propertyName, delegate { return null; });
            //---------------Test Result -----------------------
            Assert.IsTrue(collectionDelegatesDictionary.ContainsKey(propertyName));
            Assert.IsTrue(collectionDelegatesDictionary.ContainsKey(propertyName.ToUpper()));
            Assert.IsTrue(collectionDelegatesDictionary.ContainsKey(propertyName.ToLower()));
            Assert.IsNotNull(collectionDelegatesDictionary[propertyName]);
            Assert.IsNotNull(collectionDelegatesDictionary[propertyName.ToUpper()]);
            Assert.IsNotNull(collectionDelegatesDictionary[propertyName.ToLower()]);
        }

        [Test]
        public void Test_ModelClasses_OrderedForDeletion()
        {
            //---------------Set up test pack-------------------
            CollectionDelegatesDictionary collectionDelegatesDictionary = new CollectionDelegatesDictionary();
            CollectionDelegate collectionDelegate = collectionDelegatesDictionary["ModelClasses_OrderedForDeletion"];

            List<DMClass> expectedModelClasses;
            List<DMClass> dmClasses = TestUtilsCodeGen.GetParentChildHeirarchy(out expectedModelClasses);
            DMSolution dmSolution = new DMSolution();
            DMAssembly dmAssembly = new DMAssembly(TestUtilsCodeGen.GetRandomString());
            dmSolution.Assemblies.Add(dmAssembly);
            foreach (DMClass dmClass in dmClasses)
            {
                dmAssembly.Classes.Add(dmClass);
            }
            //---------------Assert Precondition----------------`

            //---------------Execute Test ----------------------
            IEnumerable<IModelElement> reorderedClasses = collectionDelegate(dmSolution);
            //---------------Test Result -----------------------
            IList<IModelClass> modelClassesCopy = new List<IModelClass>();
            foreach (DMClass dmClass in dmClasses)
            {
                modelClassesCopy.Add(dmClass);
            }
            IList<IModelElement> reorderedClassesFromUtilities = Utilities.OrderModelClassesForDeletion
                (modelClassesCopy);
            Assert.AreEqual(expectedModelClasses, reorderedClasses);
            Assert.AreEqual(reorderedClassesFromUtilities, reorderedClasses);
        }

        [Test]
        public void Test_ModelClasses_OrderedForDeletion_ThrowsExceptionWhenElementNotProject()
        {
            //---------------Set up test pack-------------------
            CollectionDelegatesDictionary collectionDelegatesDictionary = new CollectionDelegatesDictionary();
            ModelPropertyStub modelPropertyStub = new ModelPropertyStub("testproperty");
            CollectionDelegate collectionDelegate = collectionDelegatesDictionary["ModelClasses_OrderedForDeletion"];
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            GenerationException exception = null;
            try
            {
                collectionDelegate(modelPropertyStub);
            }
            catch (GenerationException ex)
            {
                exception = ex;
            }
            //---------------Test Result -----------------------
            Assert.IsNotNull(exception, "GenerationException should be thrown");
        }
    }
}